package com.jjc.MyWebApp.kit;

import com.jfinal.kit.PropKit;
import com.jfinal.log.Log;
import com.jjc.MyWebApp.Constant.ConfigConstant;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

/**
 * Created by jiaji on 2017/5/10.
 */
public class IDEAKit {
    private static final Log log = Log.getLog(IDEAKit.class);
    //密钥算法
    private static final String KEY_ALGORITHM = "IDEA";
    /**
     * 加密/解密算法 / 工作模式 / 填充方式
     */
    private static final String CIPHER_ALGORITHM = "IDEA/ECB/PKCS5Padding";

    static {
        // 加入BouncyCastleProvider支持
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 生成密钥
     *
     * @return
     */
    public static SecretKey initKey() {
        SecretKey secretKey = null;
        try {
            //密钥生成器
            KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
            //初始化密钥生成器，IDEA要求密钥长度为128位
            kg.init(128);
            //生成密钥
            secretKey = kg.generateKey();
        } catch (NoSuchAlgorithmException e) {
            if (log.isErrorEnabled()) log.warn("密钥生成失败", e);
        }
        return secretKey;

    }

    /**
     * 转换密钥
     *
     * @return byte[]
     */
    public static Key toKey(byte[] key) {
        return new SecretKeySpec(key, KEY_ALGORITHM);
    }

    /**
     * 加密
     *
     * @param data 待加密数据
     * @param key  密钥
     * @return byte[] 加密数据
     */
    public static byte[] encrypt(byte[] data, byte[] key) {
        byte[] encryptStr = null;
        try {
            // 还原密钥
            Key k = toKey(key);

            // 实例化
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

            // 初始化，设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, k);

            // 执行操作
            encryptStr = cipher.doFinal(data);
        } catch (Exception e) {
            if (log.isErrorEnabled()) log.error("数据加密失败", e);
        }
        return encryptStr;
    }
    /**
     * 解密
     *
     * @param data
     *            待解密数据
     * @param key
     *            密钥
     * @return byte[] 解密数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key) {
        byte[] encryptStr = null;
        try {
        // 还原密钥
        Key k = toKey(key);

        // 实例化
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

        // 初始化，设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, k);

        // 执行操作
        encryptStr = cipher.doFinal(data);
        } catch (Exception e) {
            if (log.isErrorEnabled()) log.error("数据解密失败", e);
        }
        return encryptStr;
    }

    /**
     * 解密字符串
     *
     * @param securityKey 密钥
     * @param content     待解密的字符串
     * @return 说明：增加Base64编码
     */
    public static String decrypt(String securityKey, String content) {
        // 1. Base64解码cookie令牌
        try {
            content = new String(Base64.decodeBase64(content.getBytes("UTF-8")), "UTF-8");
        } catch (Exception e) {
            if (log.isErrorEnabled()) log.error("Base64解码异常：content = " + content, e);
            return null;
        }

        // 2. 解密cookie令牌
        byte[] securityByte = Base64.decodeBase64(content);
        byte[] keyByte = Base64.decodeBase64(securityKey);

        byte[] dataByte = null;
        try {
            dataByte = decrypt(securityByte, keyByte);
        } catch (Exception e) {
            if (log.isErrorEnabled()) log.error("解密数据异常：content = " + content, e);
            return null;
        }
        return new String(dataByte);
    }

    /**
     * 解密字符串
     * @param content 待解密的字符串
     * @return
     * 说明：增加Base64编码
     */
    public static String decrypt(String content) {
        String securityKey = PropKit.get(ConfigConstant.config_idea_security_key);
        return decrypt(securityKey, content);
    }

    /**
     * 生成加密字符串
     * @param securityKey 密钥
     * @param content	待加密的字符串
     * @return
     * 说明：增加Base64编码
     */
    public static String encrypt(String securityKey, String content) {
        byte[] authTokenByte = null;
        try {
            authTokenByte = content.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            if(log.isErrorEnabled()) log.error("字符串数据转byte异常：content = " + content, e);
            return null;
        }
        byte[] keyByte = Base64.decodeBase64(securityKey);

        // 认证cookie加密
        byte[] securityByte = null;
        try {
            securityByte = encrypt(authTokenByte, keyByte);
        } catch (Exception e) {
            if(log.isErrorEnabled()) log.error("加密数据异常：content = " + content, e);
            return null;
        }
        String securityCookie = Base64.encodeBase64String(securityByte);

        // 认证cookie Base64编码
        try {
            securityCookie = new String (Base64.encodeBase64URLSafe(securityCookie.getBytes("UTF-8")),"UTF-8");
        } catch (Exception e) {
            if(log.isErrorEnabled()) log.error("数据Base64编码异常：content = " + content, e);
            return null;
        }

        return securityCookie;
    }
    /**
     * 生成加密字符串
     * @param content 待加密的字符串
     * @return
     * 说明：增加Base64编码
     */
    public static String encrypt(String content) {
        String securityKey = PropKit.get(ConfigConstant.config_idea_security_key);
        return encrypt(securityKey, content);
    }
}

